# -*- coding: utf-8 -*-
import codecs
import os
import math
import re
import logging
import simplejson

import action
from apina import Apina


class NotLoadedException(Exception):
    """
    Poikkeus, kun pyydetään tietoja vaikka sivua ei ole ladattu.
    """

    def __init__(self, text):
        self.text = text
        
    def __str__(self):
        return self.text


class Editoitava(object):
    """
    Editoijalle annettavat sivun tiedot, joka säilöö tiedot muutoksista.
    """
    def __init__(self, parent, title, wtxt = None):
        """
        @p parent (Sivu)     apin sivudata
        @p title  (unicode)  artikkelin otsikko
        @p wtxt   (unicode)  artikkelin wikiteksti
        """
        self.parent = parent
        self._title = title
        self.rename_title = None # TODO
        self.wtxt = wtxt
        
        # Luettelo sivuun tehdyistä muutoksista, joista tehdään summary.
        self.muutokset = []
        
        # Luettelo huomautuksista jotka tallennetaan lokiin.
        self.notes = []

        # Jos asetetaan, jyrää muutokset-talukosta tehdyn summaryn.
        self._summary = None
        
        # Muutokset-taulukosta tehdyn summaryn eteen lisättävä teksti. Asetetaan `set_summary_prefix`-metodilla.
        self._prefix = ""

        # Mahdollisen lykkäyksen syy.
        self.lykkays = None

        # Asetetaan trueksi `add_info`-metodilla, jos sivulle tehdään muutoksia.
        self.muuttunut = False

        self.paused = False
        self.pause_info = None

    def pause(self, info = None):
        self.paused = True
        self.pause_info = info

    def title(self):
        """
        Palauttaa sivun titlen.
        """
        return self._title

    def is_new(self):
        """
        Palauttaa True, jos sivu on uusi, False, jos olemassa oleva.
        """
        return self.wtxt == None
        
    def add_note(self, kuvaus):
        """
        Lisää huomautuksen, joka ei aiheuta lykkäämistä eikä johdu muutoksesta.
        """
        self.notes.append(kuvaus)
        print u"NOTE: {}".format(kuvaus)

    def add_info(self, kuvaus, muuttunut = True):
        """
        Lisää uuden muutoksen listaan.
        
        Parametri muuttunut määrittää onko artikkeli muuttunut, tieto, joka saadan 
        on_muuttunut()-metodilla
        @p kuvaus (unicode)  infoteksti, joka kuvaa muutoksen tai vastaavan
        @p muuttunut (bool)  True, jos info liittyy muutokseen, False, jos ei
        """
        # Lisätään vain yksi kappale kutakin kuvausta.
        if not kuvaus in self.muutokset:
            self.muutokset.append(kuvaus)
        self.muuttunut = self.muuttunut or muuttunut

    def set_summary(self, summary):
        """
        Asettaa summaryn, joka jyrää automaattisesti luodut ja prefiksin.
        """
        self._summary = summary
        self._prefix = ""

    def set_summary_prefix(self, prefix):
        """
        Asettaa prefiksin, joka lisätään automaattisesti luotujen summaryjen eteen.
        """
        self._prefix = prefix

    def on_muuttunut(self):
        """
        Palauttaa tiedon onko artikkeliin tehty muutoksia (add_info():jen perusteella)
        
        @return (bool)
        """
        return self.muuttunut

    def lykkaa(self, selite):
        """
        Asettaa lykkäyksen syyn.
        """
        self.lykkays = selite
        print u"Lykätään. Syy: " + selite
        return False

    def set_text(self, wtxt):
        """
        Asettaa sivun tekstin, joka tallennetaan jos editointifunktio palauttaa True.
        """
        self.wtxt = wtxt
        return True
        
    def __str__(self):
        return self.title

    def __unicode__(self):
        return self.title

    def summary(self):
        """
        Luo summaryn infoteksteistä. 

        @return (unicode)
        """

        if self._summary:
            return self._summary
        return self._prefix + "; ".join(self.muutokset)


    def get_current_rev_info(self):
        return self.parent.current_rev_json()

    def undo_rev(self, rev_id):
        self.action = action.Undo(rev_id)
        return self.action

    def rename(self, title):
        """
        Muuttaa sivun nimen. TODO
        """
        self.action = action.Rename(title)
        return self.action


class Sivu(object):
    """
    Säilöö apista ladattavat tiedot.
    """
    def __init__(self, parent, title, num, data=None):
        """
        @p parent (ArtLista) lista
        @p title  (unicode)  artikkelin otsikko
        """
        self.rent = parent
        self._title = title
        self.wtxt = None

        # Sivun indeksi sivulistassa.
        self.num = num
        
        # Apista ladattu data.
        self.apidata = None
        self.prevtimestamp = None
        self.prevrevid = None

        self.data = data

    def id(self):
        """
        Palauttaa sivun id-numeron tai -1.
        """
        if self.apidata and 'pageid' in self.apidata:
            return int(self.apidata['pageid'])
        return -1

    def title(self):
        """
        Palauttaa sivun titlen. Jos sivu on olemassa palauttaa olemassa olevan sivun titlen, jos
        sivu on luotavaksi tarkoitettu palauttaa titlen, joka on annettu tiedostossa.
        """
        if self.apidata and 'title' in self.apidata:
            return self.apidata['title']
        return self._title

    def index(self):
        return self.num

    def exists(self):
        """
        Palauttaa True, jos sivu on olemassa. Olettaa, että sivun tiedot on ladattu.
        """
        if not self.apidata: raise NotLoadedException(u"Sivua ei ole ladattu: " + self.title)
        if 'missing' in self.apidata:
            return False
        return True

    def is_valid(self):
        """
        Palauttaa True, jos ei ole invalid (esim. jos otsikko on "Keskustelu:"). Olettaa, että 
        sivun tiedot on ladattu.
        """
        if not self.apidata: raise NotLoadedException(u"Sivua ei ole ladattu: " + self.title)
        if 'invalid' in self.apidata:
            return False
        return True


    def on_ladattu(self):
        """
        Palauttaa true, jos sivun tiedot on ladattu.
        """
        return self.apidata != None

    def on_editoitu(self):
        """
        Palauttaa true, jos sivu on muuttunut viimeisen latauksen jälkeen ts. sivun muutokset on tallennettu,
        mutta muutoksia ei ole ladattu.
        """
        if self.prevtimestamp != None:
            if 'revisions' not in self.apidata or self.prevtimestamp > self.apidata['revisions'][0]['timestamp']:
                return True
        return False

    def namespace(self):
        """
        Palauttaa sivun namespace-numeron.
        """
        if self.apidata and 'ns' in self.apidata:
            return self.apidata['ns']
        return None

    def current_rev_json(self):
        if self.apidata:
            if 'revisions' in self.apidata:
                return self.apidata['revisions'][0]
        return None
                
    def current_rev(self):
        """
        Palauttaa sivun nykyisen version. Olettaa, että sivu on ladattu.
        """
        rev = None
        wtxt = None
        timestamp = None
        rev = self.current_rev_json()
        if rev:
            if '*' in rev: 
                wtxt = rev['*']
                if 'timestamp' in rev:
                    timestamp = rev['timestamp']
        else:
            print u"EI REVISIONSIA MUTTA: " + unicode(self.apidata)
        return wtxt, timestamp
        

    def last_edited(self):
        rev = self.current_rev_json()
        if rev and 'timestamp' in rev:
            return rev['timestamp']
        return "tuntematon"

    def last_editor(self):
        rev = self.current_rev_json()
        if rev and 'user' in rev:
            return rev['user']
        return "tuntematon"

    def get_editoitava(self):
        # TODO
        pass


class ArtLista(object):
    # kerralla ladattavien sivujen määrä
    BUFFER = 100
    def __init__(self):

        # sisältää tiedot tällä hetkellä editoitavasta sivusta (Editoitava-olio)
        self.editoitava = None

        # hakemisto syistä ja listoista nimistä, joita ei ole editoitu
        # esim. self.lykatyt['Taivutustaulukko on jo'] = [ 'ananas', 'persikka' ]
        self.lykatyt = {}

        # hakemisto muutoksista ja listoista nimistä, joita on editoitu
        # esim. self.infot['+taivutustaulukko'] = [ 'ananas', 'persikka' ]
        self.infot = {}

        # hakemisto sivuista ja niihin lisätyistä huomautuksista
        # esim. self.infot['a'], u"Sisälsi ylimääräisiä nimiä." ]
        self.notes = {}

        # hakemisto luoduista Sivu-oliosta
        self.sivut = {}

        # järjestetty luettelo sivuotsikoista
        self.list = []
        
        self.mode = "edit"

    def set_log_prefix(self, prefix):
        self.lykatytfile = prefix + ".lykatyt.txt"
        self.infotfile   = prefix + ".infot.txt"

    def set_lykatytfile(self, tiednimi):
        self.lykatytfile = tiednimi or "./lykatyt.out"

    def set_mode(self, mode):
        self.mode = mode

    def get_mode(self):
        return self.mode

    def set_api(self, api):
        """
        @p api (Apina) 
        """
        self.api = api

    def get_api(self):
        return self.api;

    def get_entry_at(self, i):
        if i < len(self.list):
            return self.list[i]
        return None

    def is_continuable(self):
        """
        Palauttaa True, jos lista palauttaa kerrallaan vain osan koko listaa.
        """
        pass

    def get_next_part(self):
        """
        Lataa seuraavan osan listaa.
        """
        pass

    def has_more(self):
        """
        Palauttaa True, jos lista jatkuu.
        """
        pass


    
    def get_modified(self, title, wtxt_in, tiedostosta = None):
        """
        Antaa artikkelin editointiskriptille.
        @p title (unicode)        artikkelin nimi
        @p wtxt (unicode)         artikkelin wikiteksti, None, jos artikkeli on uusi
        @p tiedostosta (unicode)  tiedostosta ladu wikiteksti (aliluokkien käyttöön)
#        @p uusi (bool)            True, jos artikkeli on uusi (jolloin wtxt = None), False, jos olemassa oleva
        @return (unicode)         muokattu wikiteksti tai alkuperäinen
        """

        self.editoitava = Editoitava(self.sivut[title], title, wtxt_in)

        print u"get_modified: editoitava: " + self.editoitava.title()

        act = self.editor.edit(self.editoitava, tiedostosta)
        if type(act) is unicode:  # pelkkä teksti on lykkäyssyy
            act = action.Lykkaa(act)

        self.editoitava.action = act

        # Jos artikkeli lykättiin, "act" on lykkäyksen syy, muuten True.

        if type(act) is action.Lykkaa:
            # tallennetaan lykkäyksen syy
            self.lykkaa(act.reason)
            print u"Sivu hylätty: {} (syy: {})".format(self.editoitava.title(), act.reason)
            logging.debug(u"Sivu hylätty: {} (syy: {})".format(self.editoitava.title(), act.reason))
            # Palautetaan alkuperäinen, jos teksti on muutettu jo ennen lykkäystä.
            self.editoitava.wtxt = wtxt_in
        else:
            print u"Sivua muutettu"

        if len(self.editoitava.notes) > 0:
            self.notes[self.editoitava.title()] = self.editoitava.notes

        return self.editoitava


    def get_new_page(self, title):
        """
        Palauttaa tiedostosta luetun tekstin.

        @p title (unicode)  artikkelin nimi
        @return (unicode, unicode)/None   wikiteksti, summaryteksti
        """
        pass

    def get_titlelist(self):
        """
        Return list to show in the listbox.
        """
        return self.list


    def get_wikitext(self, title):
        """
        Palauttaa: wikiteksti (string), timestamp (string)
        """
        print u"get_wikitext: sivu: " + title

        # Jos sivua ei ole vielä ollenkaan ladattu tai ei ole ladattu uudestaan muokkauksen jälkeen.
        if not self.sivut[title].on_ladattu() or self.sivut[title].on_editoitu():
            titles = []

            # Jos sivu ladataan ensimmäistä kertaa, ladataan muita sivuja samalla. Jos
            # sivua on jo kertaalleen editoitu on käyttäjä siirtynyt taaksepäin listassa, 
            # joten silloin vain kyseinen sivu päivitetään.

            if self.sivut[title].on_editoitu():
                titles = [title]
            else:
                # Jaetaan sivulista lohkoihin (joiden koko = self.BUFFER) ja ladataan tämän sivun lohko.
                frm = int(math.floor(self.sivut[title].index()/self.BUFFER)*self.BUFFER)

                lst = self.get_titlelist()
                for i in xrange(frm, min(frm + self.BUFFER, len(lst))):
                    titles.append(lst[i])

            print u"titles: " + unicode(titles)


#            assert title in titles

            pages = self.api.get_wikitext(titles)
            for pgid in pages:
                t = pages[pgid]['title']
                self.sivut[t].apidata = pages[pgid]

        else:
            print u"Sivu '{0}' on jo ladattu eikä sitä ole muutettu".format(title)

        wtxt, tm = self.sivut[title].current_rev()

        # Palauttaa tällaisa kun sivua ei ole:
        # {'query': {'pages': {'-1': {'ns': 0, 'missing': '', 'title': 'skorde'}}}}

        # TESTI POISTA
#        wtxt = simplejson.dumps(self.sivut[title].apidata, sort_keys=True, indent=2)

        return wtxt, tm

    def rename_page(self, page, captcha_cb):
        fr_title = self.editoitava.title()
        to_title = self.editoitava.rename_title
        comm     = self.editoitava.summary()

        (onnistui, ret) = self.api.move_page(fr_title, to_title, comm, captcha_cb)
        if onnistui:
            try:
                logging.debug(u"Sivun %s uudelleennimeäminen nimelle onnistui, timestamp: %s, revid: %s\n", ret['title'], ret['newtimestamp'], ret['newrevid'])
            except: 
                print "VIRHE: ei kaikkia tietoja: {}".format(ret)

            # Tallennetaan nimi muutostenmukaisiin ryhmiin.
            for ryhma in self.editoitava.muutokset:
                if ryhma not in self.infot:
                    self.infot[ryhma] = []
                self.infot[ryhma].append(self.editoitava.title())

            if not 'nochange' in ret:
                # Tallennetaan timestamp, josta voidaan todeta onko sivu muuttunut.
                self.sivut[title].prevrevid = ret['newrevid']
                self.sivut[title].prevtimestamp = ret['newtimestamp']

        return onnistui


    def edit_page(self, page, time, captcha_cb, minor):
        """
        Välittää editoidun sivun apille.
        """
        title = self.editoitava.title()
        wtxt  = self.editoitava.wtxt
        comm  = self.editoitava.summary()

        self.editoitava = page
        print u"edit_page: editoitava: " + title
# (True, {'pageid': 351200, 'title': 'pentametrinen', 'newtimestamp': '2014-01-19T07:51:03Z', 'contentmodel': 'wikitext', 'result': 'Success', 'new': '', 'oldrevid': 0, 'newrevid': 2117835}) #
        (onnistui, ret) = self.api.edit_page(title, wtxt, time, comm, captcha_cb, minor)
        if onnistui:
            try:
                logging.debug(u"Sivun %s editointi onnistui, timestamp %s, revid %s\n", ret['title'], ret['newtimestamp'], ret['newrevid'])
            except: 
                print "VIRHE: ei kaikkia tietoja: {}".format(ret)

            # Tallennetaan nimi muutostenmukaisiin ryhmiin.
            for ryhma in self.editoitava.muutokset:
                if ryhma not in self.infot:
                    self.infot[ryhma] = []
                self.infot[ryhma].append(self.editoitava.title())

            if not 'nochange' in ret:
                # Tallennetaan timestamp, josta voidaan todeta onko sivu muuttunut.
                self.sivut[title].prevrevid = ret['newrevid']
                self.sivut[title].prevtimestamp = ret['newtimestamp']

        return onnistui


    def undo_rev(self, page, revid, time, captcha_cb, minor):
        """
        Välittää editoidun sivun apille.
        """
        title = self.editoitava.title()
        comm  = self.editoitava.summary()

        self.editoitava = page
        print u"edit_page: editoitava: " + title
# (True, {'pageid': 351200, 'title': 'pentametrinen', 'newtimestamp': '2014-01-19T07:51:03Z', 'contentmodel': 'wikitext', 'result': 'Success', 'new': '', 'oldrevid': 0, 'newrevid': 2117835}) #
        (onnistui, ret) = self.api.undo_edit(title, revid, time, comm, captcha_cb)
        if onnistui:
            try:
                logging.debug(u"Sivun %s undotus onnistui, timestamp %s, revid %s\n", ret['title'], ret['newtimestamp'], ret['newrevid'])
            except: 
                print "VIRHE: ei kaikkia tietoja: {}".format(ret)

            # Tallennetaan nimi muutostenmukaisiin ryhmiin.
            for ryhma in self.editoitava.muutokset:
                if ryhma not in self.infot:
                    self.infot[ryhma] = []
                self.infot[ryhma].append(self.editoitava.title())

            if not 'nochange' in ret:
                # Tallennetaan timestamp, josta voidaan todeta onko sivu muuttunut.
                self.sivut[title].prevrevid = ret['newrevid']
                self.sivut[title].prevtimestamp = ret['newtimestamp']

        return onnistui

            
    def set_script(self, o):
        """
        Asettaa Script-moduulin, jolle editoitavat tiedostot välitetään.
        """
        self.editor = o
        

    def tulosta_ryhmat(self):
        """
        Tallentaa tiedot tehdyistä muutoksista ja muuttamatta jättämisistä.
        """
        def tulosta_lista(otsikko, prefix, taulukko, tiedosto):
            f = codecs.open(tiedosto, "a", "utf-8", "replace")
            for k in taulukko:
                for l in taulukko[k]:
                    f.write(u"{}{}\t{} \n".format(prefix, k, l)) 
            f.close()

        tulosta_lista(u"Lykätyt", "l:", self.lykatyt, self.lykatytfile)

        tulosta_lista(u"Huomautukset", "n:", self.notes, self.infotfile)

        # Huom. Tulostuu vain jos sivut on tallennettu.
        tulosta_lista(u"Tallennetut", "t:", self.infot, self.infotfile)
        if self.editoitava:
            print u"# Viimeinen sana: {0} ".format(self.editoitava.title())
     
    def lykkaa(self, ryhma, title = None):
        """
        Siirtaa sanan `title` lykättyihin merkinnällä `ryhma`.
        """
        title = title or self.editoitava.title()
        if ryhma not in self.lykatyt:
            self.lykatyt[ryhma] = []
        self.lykatyt[ryhma].append(title)

    def siirra_lykattyihin(self, title):
        """
        Sivujen manuaaliseen poistamiseen GUIsta. Tänne tulevat sivut on jo ladattu, joten sivujen indeksejä
        ei tarvinne muuttaa enää.
        """
        if title in self.sivut:
            self.sivut[title].lykkaa(u"Manuaalisesti lykätty.")


class SetLista(ArtLista):
    """
    Lista set-tyypin oliosta, joilla voi suorittaa joukko-operaatioita. Listat pitää kuitenkin olla
    kokonaan ladattu.
    """

    def __init__(self, s):
        """
        @param s (set)    set-tyypin olio
        """
        super(SetLista, self).__init__()

        self.set = s

        # järjestetty luettelo titleistä
        self.list = []

        # hakemisto sivudatasta, jossa avaimena toimii title
        self.sivut = {}
        i = 0
        for item in self.set:
            title = item[2]
            self.list.append(title)
            self.sivut[title] = Sivu(self, title, i)
            i += 1

    def get_new_page(self, title):
        return None, None

    def get_titlelist(self):
        return self.list


class Testilista(ArtLista):
    def __init__(self, path, fns):
        """
        """

        super(Testilista, self).__init__()

        self.path = path
        self.lue_tiedostot(fns)

    def lue_tiedostot(self, fns):
        # Otsikkoluettelo.
        self.list = []

        for fn in fns:
            self.list.append(fn)

        for i in xrange(0, len(self.list)):
            title = self.list[i]
            self.sivut[title] = Sivu(self, title, i)
            self.sivut[title].wtxt = None


    def get_wikitext(self, title):
        wtxt = None
        fn = self.path + u"/" + title
        with codecs.open(fn, "r", "utf-8") as f:
            wtxt = f.read()
            self.sivut[title].wtxt = wtxt

        return wtxt, ""



    def get_modified(self, title, wtxt_in, oma_wtxt=None):
        # Lisätään tiedostosta ladattu teksti editointipyyntöön.
        wtxt = self.get_wikitext(title)
        return super(Testilista, self).get_modified(title, wtxt_in, wtxt)


    def get_new_page(self, title):
        wtxt = self.get_wikitext(title)

        self.editoitava = Editoitava(self.sivut[title], title, wtxt)

        return self.editoitava



class Uppilista(ArtLista):
    def __init__(self, fn):
        """
        Uppilista on tiedosto, jossa on artikkeleita siten, että jokaista artikkelia edeltää rivi:
          %title
        jossa title on artikkelin title. Tätä riviä ei lähetetä, kaikki muut lähetetään.

        Lataa tiedoston nimeltä `fn` ja luo siitä objektin.
        """

        super(Uppilista, self).__init__()

        self.name = fn
  
        self.parsi_tiedosto(fn)




    def parsi_tiedosto(self, fn):
        # Otsikkoluettelo.
        self.list = []

        # Tekstiluettelo.
        artikkelit = {}
        with codecs.open(fn, "r", "utf-8") as f:
            title = None
            while True:
                line = f.readline()
                if not line: break

                # Jos rivi on muotoa "=x=", aloitetaan uusi kohta, muuten 
                # lisätään edellisen rivin perään.
                if line[0] == '=' and line[-2] == '=' and line[1] != '=' and line[-3] != '=':
                    title = line[1:-2]
                    artikkelit[title] = u""
                    self.list.append(title)
                elif title:
                    artikkelit[title] = artikkelit[title] + line

        for i in xrange(0, len(self.list)):
            title = self.list[i]
            self.sivut[title] = Sivu(self, title, i)
            self.sivut[title].wtxt = artikkelit[title]


    def get_modified(self, title, wtxt_in, oma_wtxt=None):
        # Lisätään tiedostosta ladattu teksti editointipyyntöön.
        return super(Uppilista, self).get_modified(title, wtxt_in, self.sivut[title].wtxt)


    def get_new_page(self, title):
        return super(Uppilista, self).get_modified(title, None, self.sivut[title].wtxt)


class Uppilista2(ArtLista):
    """
    Uppilista2 on tiedosto, jossa on joka rivillä oma otsikkonsa, ; ja muita tietoja:
    punjabi;Intiassa
    """
    def __init__(self, fn, prefix=""):
        """
        Lataa tiedoston nimeltä `fn` ja luo siitä objektin.

        @p fn (unicode)      tiedoston nimi
        @p prefix (unicode)  logeihin käytettävä etuliite
        """

        super(Uppilista2, self).__init__()
        self.name = fn

        self.parsi_tiedosto(fn)


    def parsi_tiedosto(self, fn):
        # Otsikkoluettelo.
        self.list = []

        # Tekstiluettelo.
        artikkelit = {}
        with codecs.open(fn, "r", "utf-8") as f:
            i = 0
            while True:
                line = f.readline()
                if not line: break

                # ohitetaan kommenttirivit
                m = re.match(u"^[ \t]*#", line)
                if m:
                    continue
#                m = re.match(u"([^␟]+)␟+(.*)", line)
#                m = re.match(u"([^␟]+)#+(.*)", line)
                m = re.match(u"^([^;]+);(.*)", line)
                if m:
                    title = m.group(1)
                    data = m.group(2)
#                    print u"rivi: {0}: {1}".format(title, data)
                    self.list.append(title)
                    self.sivut[title] = Sivu(self, title, i)
                    self.sivut[title].wtxt = data
                else:
                    title = line.strip()
                    self.list.append(title)
                    self.sivut[title] = Sivu(self, title, i)
                    self.sivut[title].wtxt = u""

                i = i+1

    def get_modified(self, title, wtxt_in, oma_wtxt=None):
        # Lisätään tiedostosta ladattu teksti editointipyyntöön.
        return super(Uppilista2, self).get_modified(title, wtxt_in, self.sivut[title].wtxt)

    def get_new_page(self, title):
        return super(Uppilista2, self).get_modified(title, None, self.sivut[title].wtxt)




class RetLista(ArtLista):
    """
    Apin palauttamalla listalla operoiva lista. Tämän luokan oliot luodaan make_*-luokkametodeilla.
    """

    def __init__(self, qtype, query, qcont, prefix=""):
        """
        Apin palauttamalla listalla operoiva lista.
        
        @p qtype (string)  listapyynnön tyyppi esim. "backlinks"
        @p query (dict)    muut parametrit
        @p qcont (string)  listauksen jatkamiseen käytetyn parametrin nimi, esim. "blcontinue"
        """

        self.results = None

        self.qtype = qtype
        self.query = query
        self.qcont = qcont

        super(RetLista, self).__init__()

    def is_continuable(self):
        return True

    def get_new_page(self, title):
        return super(RetLista, self).get_modified(title, None, self.sivut[title].wtxt)

    def get_titlelist(self):
        """
        Palauttaa koko tähän asti ladatun listan.
        """
        if self.results != None:
            self.list = map(lambda a: a['title'], self.results)

        # VÄLIAIKAINEN verbitaivutusten lisäykseen
#        self.list = map(lambda a: ((a[0:len(u"Liite:Verbitaivutus/suomi/")] != u"Liite:Verbitaivutus/suomi/" ) and (u"Liite:Verbitaivutus/suomi/" + a)) or a, self.list)

        return self.list

    def get_next_part(self):
        """
        Lataa seuraavan osan listaa.
        """

        # Jos ladataan ensimmäistä kertaa.
        if self.results == None:
            pohja = 0
        else:
            # lisätään tai vaihdetaan xxcontinue arvo
            self.query[self.qcont] = self.results.ticket
            pohja = len(self.list)

        # Haetaan tiedot ja tallennetaan ne sivutaulukkoon.
        al = self.api.list_query(self.query, self.qtype, self.qcont)
        for i in xrange(len(al)):
            title = al[i]['title']
            # VÄLIAIKAINEN verbitaivutusten lisäykseen
#            title = u"Liite:Verbitaivutus/suomi/" + title
            self.sivut[title] = Sivu(self, title, pohja+i)

        # Tehdään lista pelkistä otsikoista.
        self.list = self.list + map(lambda a: a['title'], al)

        # TODO tarviiko mihinkään??
        if self.results == None:
            self.results = al
        else:
            self.results.merge(al)

        lista = map(lambda a: a['title'], al.list)
        
        print u"EI-FILTTERÖITY: " + ",".join(lista)
        # filtteröidään
#        if self.editor.filter:
#            lista = filter(self.editor.filter, lista)
#            print u"FILTTERÖITY: " + ", ".join(lista)

        # VÄLIAIKAINEN verbitaivutusten lisäykseen
#        lista = map(lambda a: u"Liite:Verbitaivutus/suomi/" + a, lista)

        return lista

        
    def has_more(self):
        return self.results.continues()


    @staticmethod
    def make_ext_url_usage(url, protocol=None, namespaces=[], props=[], limit=None, continu=None):
        """
        Ks. vastaava metodi `apina.py`:stä.
        """

        query = { 
            'action'        : 'query', 
            'list'          : 'exturlusage', 
            'euquery'       : url, 
            'euprotocol'    : protocol, 
            'eunamespace'   : (namespaces != [])   and "|".join(map(str, map(str, namespaces))), 
            'euprop'        : (props != [])        and "|".join(props), 
            'eulimit'       : limit                and limit, 
#            'euoffset'      : continu              and continu, 
            }

        qcont = "euoffset"
        qtype = "exturlusage"

        return RetLista(qtype, query, qcont)


    @staticmethod
    def make_embedded_in(title, namespaces=[], filterredir=None, limit=None, continu=None):
        """
        Ks. vastaava metodi `apina.py`:stä.
        """

        query = { 
            'action'        : 'query', 
            'list'          : 'embeddedin', 
            'eititle'       : title, 
            'einamespace'   : (namespaces != [])   and "|".join(map(str, namespaces)), 
            'eifilterredir' : filterredir          and filterredir, 
            'eilimit'       : limit                and limit, 
#            'eicontinue'    : continu              and continu, 
            }

        qcont = "eicontinue"
        qtype = "embeddedin"

        return RetLista(qtype, query, qcont)


    @staticmethod
    def make_category_members(category, namespaces=[], types=[], limit=None, props=[], 
                              dir=None, continu=None):
        """
        Ks. vastaava metodi `apina.py`:stä.
        """

        query = { 
            'action'      : 'query', 
            'list'        : 'categorymembers', 
            'cmtitle'     : (str(category) == category) and category, 
            'cmpageid'    : (str(category) != category) and category, 
            'cmnamespace' : (namespaces != [])          and "|".join(map(str, namespaces)), 
            'cmtype'      : (types != [])               and "|".join(types), 
            'cmprop'      : (props != [])               and "|".join(props), 
            'cmlimit'     : limit, 
            'cmdir'       : dir                         and dir,
#            'cmcontinue'  : continu                     and continu, 
            }

        qcont = "cmcontinue"
        qtype = "categorymembers"

        return RetLista(qtype, query, qcont)


    @staticmethod
    def make_image_usage(page, filterredir=None, namespaces=[], redirect=None, limit=None, continu=None):
        """
        Ks. vastaava metodi `apina.py`:stä.

        Huom. ei löydä Commonsin kuvia.
        """
        query = { 
            'action'        : 'query', 
            'list'          : 'imageusage', 
            'iutitle'       : (str(page) == page)  and page, 
            'iupageid'      : (str(page) != page)  and page, 
            'iufilterredir' : filterredir          and filterredir, 
            'iunamespace'   : (namespaces != [])   and "|".join(map(str, map(str, namespaces))), 
            'iuredirect'    : redirect             and redirect, 
            'iulimit'       : limit                and limit, 
#            'iucontinue'    : continu              and continu, 
            }

        qcont = "iucontinue"
        qtype = "imageusage"

        return RetLista(qtype, query, qcont)


    @staticmethod
    def make_backlinks(page, namespaces=[], dir=None, filterredir=None, limit=None):
        """
        Ks. vastaava metodi `apina.py`:stä.
        """
        query = { 
            'action'        : 'query', 
            'list'          : 'backlinks', 
            'bltitle'       : (str(page) == page)  and page, 
            'blpageid'      : (str(page) != page)  and page, 
            'blfilterredir' : filterredir          and filterredir, 
            'blnamespace'   : (namespaces != [])   and "|".join(map(str, map(str, namespaces))), 
            'bldir'         : dir                  and dir, 
            'bllimit'       : limit                and limit, 
            }

        qcont = "blcontinue"
        qtype = "backlinks"

        return RetLista(qtype, query, qcont)

    @staticmethod
    def make_allpages(from_title=None, prefix=None, namespaces=[], dir=None, filterredir=None, limit=None):
        """
        Ks. vastaava metodi `apina.py`:stä.
        """
        query = { 
            'action'        : 'query', 
            'list'          : 'allpages', 
            'apfrom'        : (str(from_title) == from_title)  and from_title, 
            'apprefix'      : (str(prefix) == prefix)  and prefix, 
            'apfilterredir' : filterredir          and filterredir, 
            'apnamespace'   : (namespaces != [])   and "|".join(map(str, map(str, namespaces))), 
            'apdir'         : dir                  and dir, 
            'aplimit'       : limit                and limit, 
            }

        qcont = "apcontinue"
        qtype = "allpages"

        return RetLista(qtype, query, qcont)



    @staticmethod
    def make_user_contribs(user, namespaces=[], dir=None, limit=None, start=None, end=None, props=[], continu=None):
        """
        """
        query = { 
            'action'        : 'query', 
            'list'          : 'usercontribs', 
            'ucuser'        : (str(user) == user)  and user, 
            'ucnamespace'   : (namespaces != [])   and "|".join(map(str, map(str, namespaces))), 
            'ucdir'         : dir                  and dir, 
            'uclimit'       : limit                and limit, 
            'ucstart'       : start                and start, 
            'ucend'         : end                  and end, 
            'ucprop'        : (props != [])        and "|".join(props), 
            'uccontinue'    : continu              and continu, 
            }

        return RetLista("usercontribs", query, "uccontinue")

